﻿#region License
/* Copyright (C) 2009 Tim Coulter
 * 
 * This file is part of ExtremeML.
 * 
 * ExtremeML is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License, as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
*/
#endregion

using System;
using DocumentFormat.OpenXml.Spreadsheet;
using ExtremeML.Core;

namespace ExtremeML.Spreadsheet
{
	// This is a partial class that adds custom functionality to its auto-generated partner.
	public sealed partial class RowWrapperCollection
	{
		#region Custom Properties

		/// <summary>
		/// Gets the containing <see cref="WorksheetWrapper"/>.
		/// </summary>
		public WorksheetWrapper Worksheet
		{
			get { return ((WorksheetWrapper)Parent.Parent); }
		}

		#endregion
		#region Custom Methods

		/// <summary>
		/// Returns whether this collection contains a row wrapper having the specified row index.
		/// </summary>
		/// <param name="index">The zero-based row index of the target row.</param>
		/// <returns>A value that indicates whether a matching row wrapper exists.</returns>
		internal bool Contains(
			int index)
		{
			return Find(index) != null;
		}

		/// <summary>
		/// Returns the wrapper for the row having the specified index.
		/// </summary>
		/// <param name="index">The zero-based index of the target row.</param>
		/// <returns>A <see cref="RowWrapper"/> that matches the specified index. <c>null</c> if no match is found.</returns>
		internal RowWrapper Find(
			int index)
		{
			if (index < 0) throw new ArgumentOutOfRangeException("index");

			// The index of an item in its collection is not necessarily the
			// same as its RowIndex (due to sparse markup optimization). It
			// is therefore essential to retrieve matches using comparison.
			return Items.Find(item => item.RowSpan.Begin == index);
		}

		/// <summary>
		/// Returns a <see cref="RowWrapper"/> that wraps a new <see cref="Row"/>.
		/// </summary>
		/// <param name="index">The zero-based row index of the row wrapper to create.</param>
		/// <returns>A new instance of <see cref="RowWrapper"/>.</returns>
		internal RowWrapper Add(
			int index)
		{
			if (index < 0) throw new ArgumentOutOfRangeException("index");

			var result = Add();
			result.RowSpan.Begin = index;
			result.RowSpan.End = index;
			result.RowSpan.BeginAbsolute = false;
			result.RowSpan.EndAbsolute = false;
			result.Activate();
			return result;
		}

		/// <summary>
		/// Returns the visible height (in pixels) of the row having the specified index.
		/// </summary>
		/// <param name="rowIndex">The zero-based index of the target row.</param>
		/// <returns>An <see cref="int"/> that specifies the visible width of the specified row.</returns>
		internal int GetVisibleHeight(
			int rowIndex)
		{
			var row = Find(rowIndex);

			if (row == null)
			{
				// When no explicit row definition exists we use default values.
				return Utility.PointsToPixels(Worksheet.SheetFormatProperties.DefaultRowHeight.Value);
			}
			else
			{
				// Use the explicitly defined height.
				if (row.Hidden.HasValue && row.Hidden.Value)
				{
					// Hidden rows (explicit hiding or collapsed outlining) have zero width.
					return 0;
				}
				else if (!row.CustomHeight.HasValue || !row.CustomHeight.Value)
				{
					// This is an explicit row definition with default height.
					return Utility.PointsToPixels(Worksheet.SheetFormatProperties.DefaultRowHeight.Value);
				}
				else
				{
					// Visible row height is calculated from defined row height.
					if (row.Height.HasValue)
					{
						return Utility.PointsToPixels(row.Height.Value);
					}
					else
					{
						throw new PackageException("Underlying package element definition is incomplete.");
					}
				}
			}
		}

		#endregion
		#region Overrides

		/// <summary>
		/// Implements custom persistence functionality.
		/// </summary>
		protected override void OnCustomRecomposing()
		{
			// The row list must be in index sequence before persistence
			Items.Sort((a, b) => a.RowSpan.CompareTo(b.RowSpan));
		}

		#endregion
		#region Implementation Methods


		#endregion
		#region Static Methods


		#endregion
	}
}
